import re

from qturboframe.lib.report.log import logger
from qturboframe.lib.utils.check import CheckBasic
from qturboframe.lib.webdriver.exceptions import SeleniumError

from .base_element import BaseElement


class Tree(BaseElement, CheckBasic):
    '''
    Jres2.0的树形结构操作

    :Attributes:
     - _driver: 控件所在的当前webdriver对象
     - _element: 控件元素webelement对象
     - timeout: 步骤操作的超时时间

    :Example:
     - 例1: Tree(webelement)
     - 例2: Tree({By.NAME:'name'})
     - 例3: Tree({By.CLASS_NAME:'class_name','text':'文本信息'})
     - 例4: Tree({By.CLASS_NAME:'class_name','text':'文本信息'}, father=driver)
     - 例5: Tree({By.CLASS_NAME:'class_name','text':'文本信息'}, father=webelement)
    '''

    def __init__(self, element_para, father=None, timeout=5):
        super().__init__(element_para, father, timeout)


    def get_node_by_value(self, value, flag=1):
        '''
        根据Jres2.0的树组件的层级关系定位node

        :Args:
         - value: 树形结构顺序点击的节点值，例：XX1/XX2/XX3
         - idname: 树形结构的定位条件
         - idname[0]: 元素查找方式
         - idname[1]: 元素查找语句
         - idname[2]: 查找的辅助属性
         - father: tree的祖先级元素，可以给树形控件查找限定范围，这样就不需要在整个页面中查找
         - flag: 树形结构是否复选，0表示单选，1表示复选

        :Returns:
            选择成功返回True，选择失败返回False

        :Example:
         - 例: input_type.get_node_by_value("12345")
        '''
        try:
            # 判断参数的正确性
            if isinstance(value, str):
                value = [value]
            elif isinstance(value, list):
                pass
            else:
                raise SeleniumError('value参数化不正确，只能是string或者list类型！')
            re_choose_class = r'checkbox_true_full'
            re_nochoose_class = r'checkbox_false_full'

            if 'ztree' not in self._element.get_attribute("class"):
                up_div = self._element.find_element_by_attribute('css selector', 'div.ztree', timeout=self.timeout)

            # 如果是复选，先遍历
            if flag:
                lis = up_div.find_elements_by_attribute('xpath', './li', timeout=self.timeout)
                if len(value) == 1 and value[0] == 'all':
                    # 全选
                    for li in lis:
                        span = li.find_element_by_attribute("xpath","./span", assist="class:chk", timeout=self.timeout)
                        for i in range(0, 3):
                            if not re.search(re_choose_class, span.get_attribute('class')):
                                span.secure_click()
                            else:
                                break
                    return True
                else:
                    # 清空
                    for li in lis:
                        span = li.find_element_by_attribute("xpath", "./span", assist="class:chk", timeout=self.timeout)
                        for i in range(0, 3):
                            if not re.search(re_nochoose_class, li.get_attribute('class')):
                                span.secure_click()
                            else:
                                break
            # 选项选择
            for temp_value in value:
                valuelist = temp_value.split("/")
                if len(valuelist) > 1:
                    last_value = valuelist[-1]
                    del valuelist[-1]
                    temp_ul = up_div
                    for va in valuelist:
                        if temp_ul is not None:
                            up_div = self.__find_node_by_nodename(temp_ul, va)
                            temp_ul = up_div
                else:
                    temp_ul = up_div
                    last_value = valuelist[0]
                if temp_ul is not None:
                    if flag:
                        logger.info("选择树形节点：" + last_value)
                        link = temp_ul.find_element_by_attribute('link text', last_value,
                                                                 timeout=self.timeout)
                        span = link.find_element_by_attribute('xpath',
                                                              './preceding-sibling::span,class:chk',
                                                              timeout=self.timeout)
                        span.secure_click()
                    else:
                        logger.info('选择树形节点：' + last_value)
                        xpath = ".//a/span[contains(text(), '{}')]/ancestor::a".format(last_value)
                        element = temp_ul.find_element_by_attribute('xpath', xpath,timeout=self.timeout)
                        self._driver.execute_script("arguments[0].click();", element)
            return True
        except Exception as msg:
            logger.warn(str(msg))
            return False

    def __find_node_by_nodename(self, element, value):
        '''
        根据树组件的name值定位node

        :Args:
         - element: node节点的父级元素，一般为ul
         - value: node节点的显示文本

        :Returns:
            返回node节点下的第一层ul元素
        '''
        re_open_span = r'noline_open'
        re_open_span_1 = r'center_open'
        lis = element.find_elements_by_attribute('xpath', './li', timeout=self.timeout)
        for li in lis:
            if value in li.find_element_by_attribute('xpath', './a').text:
                logger.debug("打开树形节点：" + value)
                span = li.find_element_by_attribute('xpath', './span', 'class:switch', timeout=self.timeout)
                if not re.search(re_open_span, span.get_attribute('class')) and not re.search(re_open_span_1, span.get_attribute("class")):
                    self._driver.execute_script("arguments[0].click();", span)
                try:
                    ul = li.find_element_by_attribute('xpath', './ul', timeout=self.timeout)
                except SeleniumError:
                    return None
                except NoDisplayError:
                    return None
                return ul
        return None